Function: diff-unified->context
diff-unified->context is an interactive and byte-compiled function
defined in diff-mode.el.gz.
Signature
(diff-unified->context START END)
Documentation
Convert unified diffs to context diffs.
START and END are either taken from the region (if a prefix arg is given) or else cover the whole buffer.
Key Bindings
Source Code
;; Defined in /usr/src/emacs/lisp/vc/diff-mode.el.gz
;;;;
;;;; Conversion functions
;;;;
;;(defvar diff-inhibit-after-change nil
;; "Non-nil means inhibit `diff-mode's after-change functions.")
(defun diff-unified->context (start end)
"Convert unified diffs to context diffs.
START and END are either taken from the region (if a prefix arg is given) or
else cover the whole buffer."
(interactive (if (or current-prefix-arg (use-region-p))
(list (region-beginning) (region-end))
(list (point-min) (point-max))))
(unless (markerp end) (setq end (copy-marker end t)))
(let (;;(diff-inhibit-after-change t)
(inhibit-read-only t))
(save-excursion
(goto-char start)
(while (and (re-search-forward
(concat "^\\(\\(---\\) .+\n\\(\\+\\+\\+\\) .+\\|"
diff-hunk-header-re-unified ".*\\)$")
nil t)
(< (point) end))
(combine-after-change-calls
(if (match-beginning 2)
;; we matched a file header
(progn
;; use reverse order to make sure the indices are kept valid
(replace-match "---" t t nil 3)
(replace-match "***" t t nil 2))
;; we matched a hunk header
(let ((line1 (match-string 4))
(lines1 (or (match-string 5) "1"))
(line2 (match-string 6))
(lines2 (or (match-string 7) "1"))
;; Variables to use the special undo function.
(old-undo buffer-undo-list)
(old-end (marker-position end))
(start (match-beginning 0))
(reversible t))
(replace-match
(concat "***************\n*** " line1 ","
(number-to-string (+ (string-to-number line1)
(string-to-number lines1)
-1))
" ****"))
(save-restriction
(narrow-to-region (line-beginning-position 2)
;; Call diff-end-of-hunk from just before
;; the hunk header so it can use the hunk
;; header info.
(progn (diff-end-of-hunk 'unified) (point)))
(let ((hunk (buffer-string)))
(goto-char (point-min))
(if (not (save-excursion (re-search-forward "^-" nil t)))
(delete-region (point) (point-max))
(goto-char (point-max))
(let ((modif nil) last-pt)
(while (progn (setq last-pt (point))
(= (forward-line -1) 0))
(pcase (char-after)
(?\s (insert " ") (setq modif nil) (backward-char 1))
(?+ (delete-region (point) last-pt) (setq modif t))
(?- (if (not modif)
(progn (forward-char 1)
(insert " "))
(delete-char 1)
(insert "! "))
(backward-char 2))
(?\\ (when (save-excursion (forward-line -1)
(= (char-after) ?+))
(delete-region (point) last-pt)
(setq modif t)))
;; diff-valid-unified-empty-line.
(?\n (insert " ") (setq modif nil)
(backward-char 2))
(_ (setq modif nil))))))
(goto-char (point-max))
(save-excursion
(insert "--- " line2 ","
(number-to-string (+ (string-to-number line2)
(string-to-number lines2)
-1))
" ----\n" hunk))
;;(goto-char (point-min))
(forward-line 1)
(if (not (save-excursion (re-search-forward "^\\+" nil t)))
(delete-region (point) (point-max))
(let ((modif nil) (delete nil))
(if (save-excursion (re-search-forward "^\\+.*\n-"
nil t))
;; Normally, lines in a substitution come with
;; first the removals and then the additions, and
;; the context->unified function follows this
;; convention, of course. Yet, other alternatives
;; are valid as well, but they preclude the use of
;; context->unified as an undo command.
(setq reversible nil))
(while (not (eobp))
(pcase (char-after)
(?\s (insert " ") (setq modif nil) (backward-char 1))
(?- (setq delete t) (setq modif t))
(?+ (if (not modif)
(progn (forward-char 1)
(insert " "))
(delete-char 1)
(insert "! "))
(backward-char 2))
(?\\ (when (save-excursion (forward-line 1)
(not (eobp)))
(setq delete t) (setq modif t)))
;; diff-valid-unified-empty-line.
(?\n (insert " ") (setq modif nil) (backward-char 2)
(setq reversible nil))
(_ (setq modif nil)))
(let ((last-pt (point)))
(forward-line 1)
(when delete
(delete-region last-pt (point))
(setq delete nil)))))))
(unless (or (not reversible) (eq buffer-undo-list t))
;; Drop the many undo entries and replace them with
;; a single entry that uses diff-context->unified to do
;; the work.
(setq buffer-undo-list
(cons (list 'apply (- old-end end) start (point-max)
'diff-context->unified start (point-max))
old-undo)))))))))))